/*	Copyright 2007 - Xavier Baro (xbaro@cvc.uab.cat)

	This file is part of eapmlib.

    Eapmlib is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or any 
	later version.

    Eapmlib is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "AdditiveClassEnsemble.h"

Evolutive::CAdditiveClassEnsemble::CAdditiveClassEnsemble(void) : CClassEnsemble()
{
#ifndef USE_OPENCV
	OPENCV_ERROR_CLASS("CAdditiveClassEnsemble");
#endif
}

Evolutive::CAdditiveClassEnsemble::~CAdditiveClassEnsemble(void)
{		
	//m_ClassWeight.clear();
}

#ifdef USE_OPENCV
double Evolutive::CAdditiveClassEnsemble::Apply(CData *InputData)
{		
	register int i;
	double Value=0.0;
	double ClassVal;
	Evolutive::CClassifier *pClass=NULL;

	if(m_ClassWeight.size()>0)
	{
		for(i=0;i<GetNumClassifiers();i++)
		{
			//! Point to the classifier
			pClass=GetClassifier(i);

			//! Apply the classifier
			ClassVal=pClass->Apply(InputData);
			
			//! Use the weight
			Value+=ClassVal*m_ClassWeight[i];			
		}
	}
	else
	{
		for(i=0;i<GetNumClassifiers();i++)
		{
			//! Point to the classifier
			pClass=GetClassifier(i);

			//! Apply the classifier
			ClassVal=pClass->Apply(InputData);
			
			//! Use the weight
			Value+=ClassVal;			
		}
	}
	
	return Value;
}

double Evolutive::CAdditiveClassEnsemble::GetWeight(int Idx)
{
	if(Idx<0 || Idx>=GetNumClassifiers())
	{
		throw CEvolutiveLibException("Index out of bounds",__FILE__,__LINE__,"GetWeight");
	}

	return m_ClassWeight[Idx];
}

void Evolutive::CAdditiveClassEnsemble::AddClassifier(CClassifier *Classifier)
{
	// Use a default weight of 1
	AddClassifier(Classifier,1.0);
}

void Evolutive::CAdditiveClassEnsemble::AddClassifier(CClassifier *Classifier,double Weight)
{
	// Set the weight of this classifier
	m_ClassWeight.push_back(Weight);

	// Set the classifier using the base class method
	CClassEnsemble::AddClassifier(Classifier);
}

void Evolutive::CAdditiveClassEnsemble::Serialize(std::fstream &fs,bool Saving)
{
	int NumWeights;
	register int i;
	double Value;

	// Call the base class method
	CClassEnsemble::Serialize(fs,Saving);

	// Implement the specialized code
	if(Saving)
	{
		// Save the data to a file
		// Store the number of weights
		NumWeights=m_ClassWeight.size();
		fs.write((char*)&NumWeights,sizeof(int));

		// Store each weight
		for(i=0;i<NumWeights;i++)
		{			
			Value=m_ClassWeight[i];
			fs.write((char*)&Value,sizeof(double));
		}
	}
	else
	{
		// Load the data from a file
		// Read the number of weights
		fs.read((char*)&NumWeights,sizeof(int));

		// Remove old data		
		m_ClassWeight.clear();

		// Load the new weights
		for(i=0;i<NumWeights;i++)
		{		
			fs.read((char*)&Value,sizeof(double));
			m_ClassWeight.push_back(Value);
		}
	}	
}
#endif //USE_OPENCV